#include "blockqueue.hpp"
#include "Thread_mutex.hpp"

using namespace std;

pthread_mutex_t val = PTHREAD_MUTEX_INITIALIZER;

void funcofmain(TDataBlock& bd)
{
    pthread_mutex_lock(&val);
    static int cnt1 = 0;
    while(true)
    {
        bd.Push(cnt1);          
        cnt1++;
        pthread_mutex_unlock(&val);
        sleep(1);     
    }
    
}

void funcofless(TDataBlock& bd)
{
    pthread_mutex_lock(&val);
    static int cnt2 = 0;
    while(true)
    {
        bd.Pop(cnt2);   
        pthread_mutex_unlock(&val);
        sleep(1);      
    }
    
}

// vector<TDataBlock*> del;
// del.push_back(td);

void CommFunc(vector<TYPE>& vtb, int pthreadnum, function<void(TDataBlock&)> func, string what, BlockQueue<DataType>& bq)
{
    for(int i=0; i<pthreadnum; i++)
    {     
        string thread_name = what + "-thread-" + to_string(i+1);
      
        vtb.emplace_back(func, bq);
        vtb.back().Start();                  
    }
}

void MainThread(vector<TYPE>& vtb, int pthreadnum, BlockQueue<DataType>& bq)
{
    CommFunc(vtb, pthreadnum, funcofmain, "main", bq);
}

void LessThread(vector<TYPE>& vtb, int pthreadnum, BlockQueue<DataType>& bq)
{
    CommFunc(vtb, pthreadnum, funcofless, "less", bq);
}

void WaitThread(vector<TYPE>& vtb)
{
    for(auto &e: vtb) e.Join();
}

// int main()
// {
//     int a = 10;

//     vector<TYPE> vtb1, vtb2;  
//     BlockQueue<DataType>* bq = new BlockQueue<DataType>(a);

//     MainThread(vtb1, 1, *bq);
//     LessThread(vtb2, 1, *bq);

//     WaitThread(vtb1);
//     WaitThread(vtb2);
//     return 0;
// }

int main()
{
    int a = 10;

    vector<TYPE> vtb;
    BlockQueue<DataType>* bq = new BlockQueue<DataType>(a);

    MainThread(vtb, 3, *bq);
    LessThread(vtb, 2, *bq);

    WaitThread(vtb);
    

    return 0;
}



//---------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------


// void funcofmain(TDataBlock& bd)
// {
//     int cnt = 0;
//     while(true)
//     {
//         bd.Push(cnt);
//         cout  << "--funcofmain" << ">>生产cnt: " << cnt << endl;
//         sleep(1);

//         cnt++;
//     }
// }

// void funcofless(TDataBlock& bd)
// {
//     int cnt = 0;
//     while(true)
//     {
//         bd.Pop(cnt);
//         cout << "--funcofless" <<  ">>消费cnt: " << cnt << endl;
//         sleep(1);
//     }
// }

// void CommFunc(vector<TYPE>& vtb, int pthreadnum, function<void(TDataBlock&)> func, string what, BlockQueue<DataType>& bq)
// {
//     for(int i=0; i<pthreadnum; i++)
//     {     
//         string thread_name = what + "-thread-" + to_string(i+1);
        
//         vtb.emplace_back(func, bq, thread_name);
//         vtb.back().Start();                  
//     }
// }

// void MainThread(vector<TYPE>& vtb, int pthreadnum, BlockQueue<DataType>& bq)
// {
//     CommFunc(vtb, pthreadnum, funcofmain, "main", bq);
// }

// void LessThread(vector<TYPE>& vtb, int pthreadnum, BlockQueue<DataType>& bq)
// {
//     CommFunc(vtb, pthreadnum, funcofless, "less", bq);
// }

// void WaitThread(vector<TYPE>& vtb)
// {
//     for(auto &e: vtb) e.Join();
// }

// int main()
// {
//     int a = 10;
//     BlockQueue<int> *bq = new BlockQueue<int>(a);
//     vector<TYPE> vtb;

//     MainThread(vtb,1,*bq);
//     LessThread(vtb,1,*bq);
//     WaitThread(vtb);

//     return 0;
// }

//---------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------

// void func(ThreadData<int>& a)
// {
//     int cnt = 10;
//     while(cnt--)
//     {
//         cout << "Yes" << endl;
//         sleep(1);
//     } 
// }

// int main()
// {

//     vector<Thread<ThreadData<int>>> vt;
    
//     int a = 10;
//     string name = "jhfd";
//     ThreadData<int>* td = new ThreadData<int>(a, name);
//     ThreadData<int>* td2 = new ThreadData<int>(a, name);

//     vt.emplace_back(func, *td);
//     vt.back().CreateRun();
//     vt.emplace_back(func, *td2);
//     vt.back().CreateRun();   

//     vt[0].Join();
//     vt[1].Join();
//     return 0;
// }